class TFMMFire extends TFProjectileFire;


var float MinHoldTime;                  // held for this time or less will do minimum damage/force. held for MaxHoldTime will do max
var float MinForce, MaxForce;           // force to other players
var float MinDamage, MaxDamage;         // damage to other players              // %damage to self (when shielding a wall)
var sound ChargingSound;                // charging sound
var xEmitter ChargingEmitter;           // emitter class while charging
var float FullyChargedTime;				// held for this long will do max damage
var sound firesounds[3];
var float charge;
var float dtime;

// jdf ---
var string ChargingForce;
var bool bStartedChargingForce;
// --- jdf

/*replication
{
	reliable if(Role==ROLE_Authority)
		charge;
}*/

simulated function DestroyEffects()
{
    if (ChargingEmitter != None)
    {
        ChargingEmitter.Destroy();
    }
	Super.DestroyEffects();
}

simulated function InitEffects()
{
	if ( Level.NetMode != NM_DedicatedServer )
	{
		ChargingEmitter = Spawn(class'TaskForces.TFGaussCharge');
		ChargingEmitter.mRegenPause = true;
	}
    bStartedChargingForce = false;  // jdf

    Super.InitEffects();
}

function DrawMuzzleFlash(Canvas Canvas)
{
    if (ChargingEmitter != None && HoldTime > 0.0 && !bNowWaiting)
    {
		ChargingEmitter.SetLocation( Weapon.GetEffectStart() );
        Canvas.DrawActor( ChargingEmitter, false, false, Weapon.DisplayFOV );
    }

    if (FlashEmitter != None)
    {
        FlashEmitter.SetLocation( Weapon.GetEffectStart() );
        if ( Weapon.WeaponCentered() )
 			FlashEmitter.SetRotation(Weapon.Instigator.GetViewRotation());
        else
			FlashEmitter.SetRotation(Weapon.Rotation);
        Canvas.DrawActor( FlashEmitter, false, false, Weapon.DisplayFOV );
    }

    if ( (Instigator.AmbientSound == ChargingSound)
		&& ((HoldTime <= 0.0) || bNowWaiting) )
        Instigator.AmbientSound = None;

}

simulated function FlashMuzzleFlash()
{
    if (FlashEmitter != None)
    {
        FlashEmitter.mGrowthRate=60*(1+charge*2);
        FlashEmitter.mSpeedRange[1]=120*(1+charge);
        FlashEmitter.mRegenRange[1] = 12*(1+charge*3);

        FlashEmitter.Trigger(Weapon, Instigator);
    }
}

simulated function CalcCharge()
{
    charge=fmin(1,(holdtime/FullyChargedTime));
    if(charge==1) charge=1.25;
}

function DoFireEffect()
{
    local Vector StartProj, StartTrace, X,Y,Z;
//    local Rotator R, Aim;
    local Vector HitLocation, HitNormal;
    local Actor Other;

    Instigator.MakeNoise(1.0);
    Weapon.GetViewAxes(X,Y,Z);

    calcCharge();

    FireSound=firesounds[rand(3)];

    StartTrace = Instigator.Location + Instigator.EyePosition();// + X*Instigator.CollisionRadius;
    StartProj = StartTrace + X*ProjSpawnOffset.X;
    if ( !Weapon.WeaponCentered() )
	    StartProj = StartProj + Weapon.Hand * Y*ProjSpawnOffset.Y + Z*ProjSpawnOffset.Z;

    Other = Trace(HitLocation, HitNormal, StartProj, StartTrace, false);
    if (Other != None)
    {
        StartProj = HitLocation;
    }

    SpawnProjectile(StartProj,AdjustAim(StartProj, AimError));
}

function projectile SpawnProjectile(Vector Start, Rotator Dir)
{
    local Projectile p;

    if( ProjectileClass != none )
        p = Spawn(ProjectileClass,,, Start, Dir);
    p.Damage *= DamageAtten;
    p.Speed *= charge*2 +1;
    p.Velocity=vector(dir)*p.speed;

    return p;
}

function PlayFiring()
{
    bStartedChargingForce = false;
    StopForceFeedback(ChargingForce);

    if (FireCount > 0)
    {
        if (Weapon.HasAnim(FireLoopAnim))
        {
            Weapon.PlayAnim(FireLoopAnim, FireLoopAnimRate, 0.0);
        }
        else
        {
            Weapon.PlayAnim(FireAnim, FireAnimRate, TweenTime);
        }
    }
    else
    {
        Weapon.PlayAnim(FireAnim, FireAnimRate, TweenTime);
    }

    Weapon.PlayOwnedSound(FireSounds[rand(3)],SLOT_Interact,TransientSoundVolume*(1+(charge/2)),,,1-(charge/3),false);
    Weapon.PlayOwnedSound(Sound'TFmedia.MMReload',SLOT_Misc,0.4,,,,false);

    ClientPlayForceFeedback(FireForce);  // jdf

    FireCount++;
}

function ServerPlayFiring()
{
    Weapon.PlayOwnedSound(FireSounds[rand(3)],SLOT_Interact,TransientSoundVolume*(1+(charge/2)),,,1-(charge/3),false);
    Weapon.PlayOwnedSound(Sound'TFmedia.MMReload',SLOT_Misc,0.8,,,,false);
}

function ModeHoldFire()
{
    SetTimer(0.05, true);
}

function Timer()
{
//    local Actor Other;
//    local Vector HitLocation, HitNormal, StartTrace, EndTrace;
//    local Rotator Aim;
    local float Regen;
    local float ChargeScale;

    calcCharge();

    if (HoldTime > 0.0 && !bNowWaiting)
    {
        if ( HoldTime>=FullyChargedTime )
        {
            bIsFiring = false;
            Instigator.AmbientSound = None;
            if (ChargingEmitter != None)
                ChargingEmitter.mRegenPause = true;
        }
        else
        {
            Instigator.AmbientSound = ChargingSound;
            ChargeScale = FMin(HoldTime, FullyChargedTime);
            if (ChargingEmitter != None)
            {
                Regen = ChargeScale * 15 + 20;
                ChargingEmitter.mRegenRange[0] = Regen;
                ChargingEmitter.mRegenRange[1] = Regen;
                ChargingEmitter.mSpeedRange[0] = ChargeScale * -20.0;
                ChargingEmitter.mSpeedRange[1] = ChargeScale * -25.0;
                Regen = FMax((ChargeScale / 20.0),0.20);
                ChargingEmitter.mLifeRange[0] = Regen;
                ChargingEmitter.mLifeRange[1] = Regen;
                ChargingEmitter.mRegenPause = false;
            }

            if (!bStartedChargingForce)
            {
                bStartedChargingForce = true;
                ClientPlayForceFeedback( ChargingForce );
            }
        }
    }
    else
    {
		if ( Instigator.AmbientSound == ChargingSound )
			Instigator.AmbientSound = None;
        SetTimer(0, false);
    }
}

simulated function vector GetFireStart(vector X, vector Y, vector Z)
{
    return Instigator.Location;
}

function StartBerserk()
{
    MaxHoldTime = default.MaxHoldTime * 0.75;
    FullyChargedTime = default.FullyChargedTime * 0.75;
}

function StopBerserk()
{
    MaxHoldTime = default.MaxHoldTime;
    FullyChargedTime = default.FullyChargedTime;
}

function PlayPreFire()
{
    Weapon.PlayAnim('Charge', 1.0/FullyChargedTime, 0.1);
}

defaultproperties
{
     MinHoldTime=0.500000
     ChargingSound=Sound'TFMedia.Marksman.MMcharge'
     FullyChargedTime=4.010000
     FireSounds(0)=Sound'TFMedia.Marksman.MMfire1'
     FireSounds(1)=Sound'TFMedia.Marksman.MMfire2'
     FireSounds(2)=Sound'TFMedia.Marksman.MMfire3'
     ChargingForce="ImpactHammerLoop"
     ProjSpawnOffset=(X=15.000000,Y=9.000000,Z=-4.000000)
     bFireOnRelease=True
     MaxHoldTime=10.000000
     TransientSoundVolume=1.000000
     PreFireAnim="Charge"
     FireLoopAnim=
     FireEndAnim=
     TweenTime=0.000000
     FireSound=sound'TFMedia.Marksman.MMfire1'
     FireForce="ShieldGunFire"
     FireRate=1.600000
     AmmoClass=Class'taskforces.TFMMGunAmmo'
     AmmoPerFire=1
     ShakeRotMag=(X=5.000000,Y=5.000000,Z=90.000000)
     ShakeRotRate=(Z=4000.000000)
     ShakeRotTime=6.000000
     ShakeOffsetMag=(Y=1.000000,Z=1.000000)
     ShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000)
     ShakeOffsetTime=3.000000
     ProjectileClass=class'taskforces.TFMMProjectile'
     BotRefireRate=1.000000
     WarnTargetPct=0.100000
     FlashEmitterClass=Class'taskforces.TFMMMuzRings'
}
